import store from '@/store/index.js'
import {
	getBrowser
} from "@/utils/yc/Browser"
import {
	UUID
} from "@/utils/yc/Id"
import {formatDate} from "@/utils/yc/Time"


class Chat {
	//初始化
	constructor() {

		this.APP_VERSION = "1.0.0";
		this.APP_CHANNEL = store.getters.channel || "web";
		this.APP_PACKAGE = "com.farsunset.cim";
		/*
		 *特殊的消息类型，999代表被服务端强制下线
		 */
		this.ACTION_999 = "999";
		this.DATA_HEADER_LENGTH = 1;
		//参考消息类型目前仅用到0,1,2和999 action={2:通讯消息(推送消息),999:强制下线退出登录,3:未定义消息体(推送消息),4:未定义消息体(回复的消息)}
		this.MESSAGE = 2;
		// 消息类型4
		this.REPLY_BODY = 4;
		// 消息类型3 登录鉴权
		this.SENT_BODY = 3;
		// 心跳接受到 马上回复
		this.PING = 1;
		// 心跳回复给服务的
		this.PONG = 0;
		/**
		 * PONG字符串转换后
		 * @type {Uint8Array}
		 */
		this.PONG_BODY = new Uint8Array([80, 79, 78, 71]);
		// import ChatModel from './chatModel.js'
		// this.chatModel = new ChatModel();
		//用户登陆token
		this.wsAccessToken = store.getters.token;
		// 是否正在建立重链
		this.isRestCon = false;
		//ws地址+ '?token=' + this.wsAccessToken;
		this.wsUrl = config.wsUrl

		//websocket对象
		this.socketTask = null;

		//心跳检测 暂时用不到了
		this.heartbeatInterval = null;
		//心跳检测时间 暂时用不到了 
		this.heartbeatTimeOut = 5000;

		//是否人为关闭
		this.isPeopleClose = false;
		//断线重连机制
		this.reconnectInterval = null;
		//重连时间
		this.reconnectTimeOut = 5000;
		//重连次数
		this.restconnectCount = 10000;
		//落网重连
		uni.onNetworkStatusChange((res) => {
			if (res.isConnected) {
				this.connect();
			}
		});

	}
	
	//单例模式
	static getInstance() {
		if (!this.instance) {
			this.instance = new Chat();
		}
		return this.instance;
	}
	bindAccount() {
		// var account = "yrk:" + "app-online-token:" + store.getters.userInfo.uid + ":" + store.getters.token;
		var account = store.getters.token;
		let deviceId = this.deviceId;
		if (deviceId == '' || deviceId == undefined) {
			deviceId = UUID();
			this.deviceId = deviceId;
		}
		let browser = getBrowser();
		var time = new Date().getTime();
		var language = "zh-CN";
		//#ifdef MP-WEIXIN
		language = "zh-CN"
		//#endif
		// #ifdef H5
		language = navigator.language
		//  #endif
		var map = {
			"token": account,
			"channel": this.APP_CHANNEL,
			"appVersion": this.APP_VERSION,
			"osVersion": browser.version,
			"packageName": this.APP_PACKAGE,
			"deviceId": deviceId,
			"deviceName": browser.name,
			"language": language
		}
		var data = {
			key: "client_bind",
			timestamp: time,
			data: map
		}
		//创建
		let msg = sendbodyModel.create(data);
		// console.log(message)
		let buf = sendbodyModel.encode(msg).finish();
		var protobuf = new Uint8Array(buf.length + 1);
		protobuf[0] = this.SENT_BODY;
		protobuf.set(buf, 1);
		this.sendMsg(protobuf)
	}
	decodeMessage(msg){

	}
	addMessage(msg) {
		// console.log(message)
		try {
			msg.content = JSON.parse(msg.content)
		} catch (e) {
			//TODO handle the exception
		}
		// console.log(message)
		// store.dispatch("addMessage", msg)
	}
	onMessage(e) {
		let	msg
		// console.log(JSON.stringify(e))
		let data = new Uint8Array(e.data);
		let type = data[0];
		let body = data.subarray(this.DATA_HEADER_LENGTH, data.length);
		console.log("CIMPushManager.onMessage______________________type:"+type+"________________________________")
		// console.log(type)
		switch (type) {
			case this.PING:
				this.pong();
				break
			case this.MESSAGE:
				// 消息
				try{
					// console.log(body)
				msg=messageModel.decode(body);
				var userinfo = {};
				if(msg.extra){
					userinfo.avatar= msg.extra.avatar??""
					userinfo.nickname= msg.extra.nickname??""
				}
				msg.sendTime =formatDate(msg.sendTime)
				msg.userinfo=userinfo
					// console.log(msg)
				}catch(e){
					console.log(e)
				}

				/*
				*被强制下线之后，不再继续连接服务端
				*/
				if (msg.action == this.ACTION_999) {
					console.log("强制下线")
					store.commit("manualStop", true)
				} else {
					this.addMessage(msg)

				}
				break
			case this.REPLY_BODY:
				// 服务端推过来的消息内容
				 msg = replyBodyModel.decode(body);
				// let message =decodeSentBodyProto(body)
				// console.log(msg)
				if (msg.key === 'client_bind') {
					var code =parseInt(msg.code)
					switch ( code) {
						case 200:
							store.commit("onConnectWs", true)
							// store.commit("manualStop", false)
							console.log('wss握手绑定成功')
							break;
						case 401:
							console.log('wss握手绑定失败')
							// 授权过期 强制退出登录
							store.commit("logout")
							break;

						default:
							break;
					}
				}
				break
				default:
					break
		}

	}
	//链接并打开
	connect() {
		try {
			if (this.isRestCon || !store.getters.hasLogin) {
				return
			}
			this.isRestCon = true
			this.socketTask = uni.connectSocket({
				url: this.wsUrl,
				// protocols:[],
				success: () => {
					this.isRestCon = false
					console.log("正在建立链接");
					return this.socketTask
				},
				fail: (err) => {
					this.isRestCon = false

					//重连
					this.reconnect();
				},
			});
			//打开链接正常
			this.socketTask.onOpen(async (res) => {
				console.log("打开链接成功");
				// 登录鉴权
				this.bindAccount()
				//清除心跳and断开重连定时器，
				clearInterval(this.heartbeatInterval);
				clearInterval(this.reconnectInterval);
				//设置重连次数
				this.reconnectCount = this.restconnectCount;
				//重置人为关闭状态
				this.isPeopleClose = false;

				//开启心跳检测
				// this.startHeartbeat();
				//监听接收消息
				this.socketTask.onMessage((res) => {
					this.onMessage(res)
					console.log("接受到消息")
					console.log(res)
				});
			})

			this.socketTask.onError((err) => {
				store.commit("onConnectWs", false)
				console.log('onError');
				//重连
				this.reconnect();
			})

			this.socketTask.onClose(() => {
				store.commit("onConnectWs", false)
				console.log('onClose');
				//重连
				this.reconnect();
			})

		} catch (e) {
			//重连
			// this.reconnect();
		}
	}
	//发送消息
	sendMsg(value) {
		var that = this
		this.socketTask.send({
			data: value.buffer,
			async success() {
				console.log('消息发送成功')
			},
			async fail() {
				store.commit("onConnectWs", false)
				//重连
				that.reconnect();
			}
		})
	}
	//手动关闭链接
	close() {
		console.log('close');
		this.isPeopleClose = true;
		this.socketTask.close({
			success(res) {
				store.commit("onConnectWs", false)
				console.log("手动关闭成功")
			},
			fail(err) {

			}
		})
	}
	pong() {
		let pong = new Uint8Array(this.PONG_BODY.byteLength + 1);
		pong[0] = this.PONG;
		pong.set(this.PONG_BODY, 1);
		// console.log(pong)
		this.sendMsg(pong);
	};
	// //心跳检测
	// startHeartbeat() {
	// 	this.heartbeatInterval = setInterval(() => {
	// 		let pong = new Uint8Array(PONG_BODY.byteLength + 1);
	// 		pong[0] = PONG;
	// 		pong.set(PONG_BODY, 1);
	// 		this.sendMsg(pong);
	// 	}, this.heartbeatTimeOut);
	// }
	//断线重连
	reconnect() {
		var that = this
		//非人为关闭则尝试重连
		console.log('尝试断线重连');
		// 如果不是强制断开链接，和不是主动断开的情况,并且当前是非链接状态 自动进行重链
		if (this.isRestCon) {
			console.log('已在重连中');
			return
		}
		console.log(store.getters.manualStop, that.isPeopleClose, store.getters.onConnectWs)
		if (!store.getters.manualStop && !that.isPeopleClose && !store.getters.onConnectWs) {
			this.isRestCon = true
			// 延时重连 防止多个链接同时进行
			that.reconnectInterval = setTimeout(() => {
				this.isRestCon = false
				//如果重连次数小于0则清除定时器
				if (that.reconnectCount > 0) {
					// 非链接状态 进行重链
					console.log('当前状态：', store.getters.onConnectWs ? "在线" : "不在线");
					if (!store.getters.onConnectWs) {
						console.log('正在重连，第', that.reconnectCount, '次');
						that.connect();
						that.reconnectCount--;
					}
				} else {
					clearInterval(that.reconnectInterval);
				}
			}, that.reconnectTimeOut);
		}
	}

}

export default Chat;
